/*!
 * \file SelMocker.h
 * \project	WonderTrader
 *
 * \author Wesley
 * \date 2020/03/30
 * 
 * \brief SEL策略模拟器头文件
 * 
 * \details 本文件定义了SEL（选股策略）模拟器SelMocker类，用于回测环境下模拟SEL策略的执行。
 *          提供完整的SEL策略上下文接口实现，支持选股算法、组合管理、信号处理、
 *          持仓调整等功能，为SEL策略回测提供完整的运行环境。
 *          
 *          主要功能包括：
 *          - 选股策略生命周期管理
 *          - 持仓设置和组合管理
 *          - 选股信号记录和执行
 *          - 历史数据访问
 *          - 策略性能统计
 *          - 策略日志输出
 */
#pragma once
#include <sstream>
#include "HisDataReplayer.h"

#include "../Includes/FasterDefs.h"
#include "../Includes/ISelStraCtx.h"
#include "../Includes/SelStrategyDefs.h"
#include "../Includes/WTSDataDef.hpp"
#include "../Share/fmtlib.h"
#include "../Share/DLLHelper.hpp"

class SelStrategy;

USING_NS_WTP;

class HisDataReplayer;

/*!
 * \class SelMocker
 * \brief SEL策略模拟器类
 * 
 * \details 该类实现了ISelStraCtx（SEL策略上下文接口）和IDataSink（数据接收接口），
 *          为SEL策略在回测环境下提供完整的运行上下文。主要功能包括：
 *          - 策略生命周期管理（初始化、运行、结束）
 *          - 选股信号生成和持仓调整
 *          - 组合持仓管理和风险控制
 *          - 历史数据访问和K线数据处理
 *          - 策略信号记录和统计
 *          - 策略日志输出和用户数据存储
 * 
 * \note 该类是回测系统的核心组件，提供与实盘环境一致的SEL策略接口
 */
class SelMocker : public ISelStraCtx, public IDataSink
{
public:
	/*!
	 * \brief 构造函数
	 * \details 创建SEL模拟器实例，初始化各项参数
	 * 
	 * \param replayer 历史数据回放器指针
	 * \param name 策略名称
	 * \param slippage 滑点设置（默认为0）
	 */
	SelMocker(HisDataReplayer* replayer, const char* name, int32_t slippage = 0);
	
	/*!
	 * \brief 析构函数
	 * \details 清理资源，导出回测结果
	 */
	virtual ~SelMocker();

private:
	/*!
	 * \brief 格式化调试日志输出
	 * \details 使用格式化字符串输出调试级别日志
	 */
	template<typename... Args>
	void log_debug(const char* format, const Args& ...args)
	{
		std::string s = fmt::sprintf(format, args...);
		stra_log_debug(s.c_str());
	}

	/*!
	 * \brief 格式化信息日志输出
	 * \details 使用格式化字符串输出信息级别日志
	 */
	template<typename... Args>
	void log_info(const char* format, const Args& ...args)
	{
		std::string s = fmt::sprintf(format, args...);
		stra_log_info(s.c_str());
	}

	/*!
	 * \brief 格式化错误日志输出
	 * \details 使用格式化字符串输出错误级别日志
	 */
	template<typename... Args>
	void log_error(const char* format, const Args& ...args)
	{
		std::string s = fmt::sprintf(format, args...);
		stra_log_error(s.c_str());
	}

private:
	/*!
	 * \brief 导出输出结果
	 * \details 将回测结果导出到文件
	 */
	void	dump_outputs();
	
	/*!
	 * \brief 记录选股信号
	 * \param stdCode 标准合约代码
	 * \param target 目标持仓
	 * \param price 信号价格
	 * \param gentime 生成时间
	 * \param usertag 用户标签
	 */
	inline void log_signal(const char* stdCode, double target, double price, uint64_t gentime, const char* usertag = "");
	
	/*!
	 * \brief 记录交易日志
	 * \param stdCode 标准合约代码
	 * \param isLong 是否多头
	 * \param isOpen 是否开仓
	 * \param curTime 当前时间
	 * \param price 成交价格
	 * \param qty 成交数量
	 * \param userTag 用户标签
	 * \param fee 手续费
	 */
	inline void	log_trade(const char* stdCode, bool isLong, bool isOpen, uint64_t curTime, double price, double qty, const char* userTag = "", double fee = 0.0);
	
	/*!
	 * \brief 记录平仓日志
	 * \param stdCode 标准合约代码
	 * \param isLong 是否多头
	 * \param openTime 开仓时间
	 * \param openpx 开仓价格
	 * \param closeTime 平仓时间
	 * \param closepx 平仓价格
	 * \param qty 平仓数量
	 * \param profit 本次盈亏
	 * \param totalprofit 累计盈亏
	 * \param enterTag 开仓标签
	 * \param exitTag 平仓标签
	 */
	inline void	log_close(const char* stdCode, bool isLong, uint64_t openTime, double openpx, uint64_t closeTime, double closepx, double qty,
		double profit, double totalprofit = 0, const char* enterTag = "", const char* exitTag = "");

	/*!
	 * \brief 更新动态盈亏
	 * \param stdCode 标准合约代码
	 * \param price 当前价格
	 */
	void	update_dyn_profit(const char* stdCode, double price);

	/*!
	 * \brief 执行持仓设置
	 * \param stdCode 标准合约代码
	 * \param qty 目标数量
	 * \param price 价格
	 * \param userTag 用户标签
	 * \param bTriggered 是否触发
	 */
	void	do_set_position(const char* stdCode, double qty, double price = 0.0, const char* userTag = "", bool bTriggered = false);
	
	/*!
	 * \brief 追加选股信号
	 * \param stdCode 标准合约代码
	 * \param qty 目标数量
	 * \param userTag 用户标签
	 * \param price 价格
	 */
	void	append_signal(const char* stdCode, double qty, const char* userTag = "", double price = 0.0);

public:
	/*!
	 * \brief 初始化SEL策略工厂
	 * \param cfg 配置参数
	 * \return 是否初始化成功
	 */
	bool	init_sel_factory(WTSVariant* cfg);

public:
	//////////////////////////////////////////////////////////////////////////
	//IDataSink接口实现 - 数据接收处理
	
	/*! \brief 处理Tick数据 */
	virtual void	handle_tick(const char* stdCode, WTSTickData* curTick) override;
	/*! \brief 处理K线收盘事件 */
	virtual void	handle_bar_close(const char* stdCode, const char* period, uint32_t times, WTSBarStruct* newBar) override;
	/*! \brief 处理定时调度事件 */
	virtual void	handle_schedule(uint32_t uDate, uint32_t uTime) override;

	/*! \brief 处理初始化事件 */
	virtual void	handle_init() override;
	/*! \brief 处理交易时段开始事件 */
	virtual void	handle_session_begin(uint32_t uCurDate) override;
	/*! \brief 处理交易时段结束事件 */
	virtual void	handle_session_end(uint32_t uCurDate) override;
	/*! \brief 处理回测完成事件 */
	virtual void	handle_replay_done() override;

	//////////////////////////////////////////////////////////////////////////
	//ISelStraCtx接口实现 - SEL策略上下文接口
	
	/*! \brief 获取策略ID */
	virtual uint32_t id() { return _context_id; }

	// 回调函数接口
	/*! \brief 策略初始化回调 */
	virtual void on_init() override;
	/*! \brief 策略交易时段开始回调 */
	virtual void on_session_begin(uint32_t curTDate) override;
	/*! \brief 策略交易时段结束回调 */
	virtual void on_session_end(uint32_t curTDate) override;
	/*! \brief 策略Tick数据回调 */
	virtual void on_tick(const char* stdCode, WTSTickData* newTick, bool bEmitStrategy = true) override;
	/*! \brief 策略K线数据回调 */
	virtual void on_bar(const char* stdCode, const char* period, uint32_t times, WTSBarStruct* newBar) override;
	/*! \brief 策略定时调度回调 */
	virtual bool on_schedule(uint32_t curDate, uint32_t curTime, uint32_t fireTime) override;
	/*! \brief 遍历持仓回调 */
	virtual void enum_position(FuncEnumSelPositionCallBack cb) override;

	/*! \brief Tick数据更新通知 */
	virtual void on_tick_updated(const char* stdCode, WTSTickData* newTick) override;
	/*! \brief K线收盘通知 */
	virtual void on_bar_close(const char* stdCode, const char* period, WTSBarStruct* newBar) override;
	/*! \brief 策略调度通知 */
	virtual void on_strategy_schedule(uint32_t curDate, uint32_t curTime) override;


	//////////////////////////////////////////////////////////////////////////
	// 策略接口
	
	/*! \brief 获取持仓数量 */
	virtual double stra_get_position(const char* stdCode, bool bOnlyValid = false, const char* userTag = "") override;
	/*! \brief 设置持仓数量 */
	virtual void stra_set_position(const char* stdCode, double qty, const char* userTag = "") override;
	/*! \brief 获取最新价格 */
	virtual double stra_get_price(const char* stdCode) override;

	/*! \brief 获取当前日期 */
	virtual uint32_t stra_get_date() override;
	/*! \brief 获取当前时间 */
	virtual uint32_t stra_get_time() override;

	/*! \brief 获取品种信息 */
	virtual WTSCommodityInfo* stra_get_comminfo(const char* stdCode) override;
	/*! \brief 获取交易时段信息 */
	virtual WTSSessionInfo* stra_get_sessinfo(const char* stdCode) override;
	/*! \brief 获取K线数据 */
	virtual WTSKlineSlice*	stra_get_bars(const char* stdCode, const char* period, uint32_t count) override;
	/*! \brief 获取Tick数据 */
	virtual WTSTickSlice*	stra_get_ticks(const char* stdCode, uint32_t count) override;
	/*! \brief 获取最新Tick数据 */
	virtual WTSTickData*	stra_get_last_tick(const char* stdCode) override;

	/*! \brief 订阅Tick数据 */
	virtual void stra_sub_ticks(const char* stdCode) override;

	/*! \brief 输出信息日志 */
	virtual void stra_log_info(const char* message) override;
	/*! \brief 输出调试日志 */
	virtual void stra_log_debug(const char* message) override;
	/*! \brief 输出错误日志 */
	virtual void stra_log_error(const char* message) override;

	/*! \brief 保存用户数据 */
	virtual void stra_save_user_data(const char* key, const char* val) override;
	/*! \brief 加载用户数据 */
	virtual const char* stra_load_user_data(const char* key, const char* defVal = "") override;

protected:
	uint32_t			_context_id;			/*!< 策略上下文ID */
	HisDataReplayer*	_replayer;				/*!< 历史数据回放器指针 */

	uint64_t		_total_calc_time;			/*!< 总计算时间（微秒） */
	uint32_t		_emit_times;				/*!< 总计算次数 */
	int32_t			_slippage;					/*!< 成交滑点（基点） */

	std::string		_main_key;					/*!< 主键信息 */

	/*!
	 * \struct _KlineTag
	 * \brief K线标记结构
	 * 
	 * 用于标记K线是否已收盘的辅助结构
	 */
	typedef struct _KlineTag
	{
		bool			_closed;				/*!< 是否已收盘 */

		_KlineTag() :_closed(false){}

	} KlineTag;
	typedef faster_hashmap<std::string, KlineTag> KlineTags;
	KlineTags	_kline_tags;					/*!< K线标记映射表 */

	typedef std::pair<double, uint64_t>	PriceInfo;
	typedef faster_hashmap<std::string, PriceInfo> PriceMap;
	PriceMap		_price_map;					/*!< 价格信息映射表，存储最新价格和时间戳 */

	/*!
	 * \struct _DetailInfo
	 * \brief 持仓明细信息结构
	 * 
	 * 记录单笔开仓的详细信息，用于计算盈亏和风险管理
	 */
	typedef struct _DetailInfo
	{
		bool		_long;					/*!< 是否多头持仓 */
		double		_price;					/*!< 开仓价格 */
		double		_volume;				/*!< 持仓数量 */
		uint64_t	_opentime;				/*!< 开仓时间（微秒时间戳） */
		uint32_t	_opentdate;				/*!< 开仓交易日 */
		double		_max_profit;			/*!< 最大浮盈 */
		double		_max_loss;				/*!< 最大浮亏 */
		double		_profit;				/*!< 当前盈亏 */
		char		_opentag[32];			/*!< 开仓标签 */

		_DetailInfo()
		{
			memset(this, 0, sizeof(_DetailInfo));
		}
	} DetailInfo;

	/*!
	 * \struct _PosInfo
	 * \brief 持仓信息结构
	 * 
	 * 汇总某个合约的全部持仓信息，包括总持仓、盈亏、明细等
	 */
	typedef struct _PosInfo
	{
		double		_volume;				/*!< 总持仓量 */
		double		_closeprofit;			/*!< 平仓盈亏 */
		double		_dynprofit;				/*!< 动态盈亏（浮盈浮亏） */
		double		_frozen;				/*!< 冻结持仓量 */

		std::vector<DetailInfo> _details;	/*!< 持仓明细列表 */

		_PosInfo()
		{
			_volume = 0;
			_closeprofit = 0;
			_dynprofit = 0;
			_frozen = 0;
		}

		/*!
		 * \brief 获取有效持仓量
		 * \return 有效持仓量（总持仓减去冻结量）
		 */
		inline double valid() const { return _volume - _frozen; }
	} PosInfo;
	typedef faster_hashmap<std::string, PosInfo> PositionMap;
	PositionMap		_pos_map;				/*!< 持仓信息映射表 */

	/*!
	 * \struct _SigInfo
	 * \brief 选股信号信息结构
	 * 
	 * 存储选股策略生成的信号信息，包括目标持仓、价格、触发状态等
	 */
	typedef struct _SigInfo
	{
		double		_volume;				/*!< 目标持仓量 */
		std::string	_usertag;				/*!< 用户标签 */
		double		_sigprice;				/*!< 信号价格 */
		double		_desprice;				/*!< 期望价格 */
		bool		_triggered;				/*!< 是否已触发执行 */
		uint64_t	_gentime;				/*!< 信号生成时间 */

		_SigInfo()
		{
			_volume = 0;
			_sigprice = 0;
			_desprice = 0;
			_triggered = false;
			_gentime = 0;
		}
	}SigInfo;
	typedef faster_hashmap<std::string, SigInfo>	SignalMap;
	SignalMap		_sig_map;				/*!< 选股信号映射表 */

	std::stringstream	_trade_logs;		/*!< 交易日志流 */
	std::stringstream	_close_logs;		/*!< 平仓日志流 */
	std::stringstream	_fund_logs;			/*!< 资金日志流 */
	std::stringstream	_sig_logs;			/*!< 信号日志流 */

	// 是否在调度中的标记
	bool			_is_in_schedule;		/*!< 是否在自动调度过程中 */

	// 用户数据
	typedef faster_hashmap<std::string, std::string> StringHashMap;
	StringHashMap	_user_datas;			/*!< 用户自定义数据映射表 */
	bool			_ud_modified;			/*!< 用户数据是否已修改 */

	/*!
	 * \struct _StraFundInfo
	 * \brief 策略资金信息结构
	 * 
	 * 记录策略的资金状态，包括总盈亏、动态盈亏和手续费等
	 */
	typedef struct _StraFundInfo
	{
		double	_total_profit;				/*!< 总盈亏（已实现） */
		double	_total_dynprofit;			/*!< 总动态盈亏（浮盈浮亏） */
		double	_total_fees;				/*!< 总手续费 */

		_StraFundInfo()
		{
			memset(this, 0, sizeof(_StraFundInfo));
		}
	} StraFundInfo;

	StraFundInfo		_fund_info;			/*!< 策略资金信息 */

	/*!
	 * \struct _StraFactInfo
	 * \brief 策略工厂信息结构
	 * 
	 * 管理策略工厂的动态库加载、实例创建和销毁等
	 */
	typedef struct _StraFactInfo
	{
		std::string		_module_path;		/*!< 模块路径 */
		DllHandle		_module_inst;		/*!< 动态库句柄 */
		ISelStrategyFact*		_fact;		/*!< 策略工厂指针 */
		FuncCreateSelStraFact	_creator;	/*!< 工厂创建函数 */
		FuncDeleteSelStraFact	_remover;	/*!< 工厂删除函数 */

		_StraFactInfo()
		{
			_module_inst = NULL;
			_fact = NULL;
		}

		~_StraFactInfo()
		{
			if (_fact)
				_remover(_fact);
		}
	} StraFactInfo;
	StraFactInfo	_factory;				/*!< 策略工厂信息 */

	SelStrategy*	_strategy;				/*!< SEL策略实例指针 */

	// Tick订阅列表
	faster_hashset<std::string> _tick_subs;	/*!< Tick数据订阅合约列表 */
};